"""
File: example_2.py
Project: 重大版信息技术8年级程序例子
File Created: 2020/02/20 13:24:26
Author: Dunmore (fovd2020@outlook.com)
---------------------------------------
Description:
1.3 思考与练习 提高部分 五子棋
---------------------------------------
"""
import time
import pygame

# 颜色定义
BOARD_BACKGROUND_COLOR = (253, 203, 110)
WHITE = (255, 255, 255)
BLACK = (0, 0, 0)
RED = (255, 0, 0)
# 格子尺寸
CELL_SIZE = 30


def draw_board(screen):
    """绘制棋盘
    
    Args:
        screen (pygame.Surface): 屏幕
    """
    for i in range(1, 16):
        # 画横线
        pygame.draw.line(
            screen,
            [0, 0, 0],
            [CELL_SIZE, i * CELL_SIZE],
            [15 * CELL_SIZE, i * CELL_SIZE],
        )
        # 画竖线
        pygame.draw.line(
            screen,
            [0, 0, 0],
            [i * CELL_SIZE, CELL_SIZE],
            [i * CELL_SIZE, 15 * CELL_SIZE],
        )
    pygame.display.update()


def judge(data, row, col, is_black):
    """判断是否一方胜利

    Args:
        data (int[][]): 落子数据的二维数组
        row (int): 当前落子在第几行
        col (int): 当前落子在第几列
        is_black (bool): 刚刚下的是黑棋还是白棋

    Returns:
        bool: 是否胜利
    """
    chess = 1 if is_black else 2

    # 要检查的四个方向的棋子的步长矢量
    # (0,1)表示横向，row每次增加0，col每次增加1
    # 以此类推
    vcotrs = [(0, 1), (1, 0), (1, 1), (1, -1)]

    # 循环测试四个方向
    for vcotor in vcotrs:
        matched_count = 0

        # 设置判断的行/列/斜线起点坐标
        # 从前面第四个棋子开始
        start_row = row - vcotor[0] * 4
        start_col = col - vcotor[1] * 4
        # 如果不足4格，从0开始，并且处理列坐标或行坐标，从相应的边缘线上的格子开始
        if start_row < 0:
            start_row = 0
            start_col = col - row
        if start_col < 0:
            start_col = 0
            start_row = row - col

        # 每个方向检查前后共9格
        for i in range(9):
            # 当前检查的行和列
            c_row = start_row + i * vcotor[0]
            c_col = start_col + i * vcotor[1]

            # 如果超过棋盘范围，退出当前方向的判断
            if c_row > 14 or c_col > 14:
                break

            # 是否和当前所下的棋子颜色一样的棋子达到5颗
            if data[c_row][c_col] == chess:
                matched_count += 1
                if matched_count == 5:
                    return True
            else:
                matched_count = 0

    # 都没有达到5颗同色，返回False
    return False


def show_winner(screen, winner):
    """绘制胜利信息

    Args:
        screen (pygame.Surface): 屏幕
        winner (str): 获胜方
    """
    font = pygame.font.SysFont("SimHei", 50)
    textft = font.render(f"{winner}获胜!", True, RED)
    textft_rect = textft.get_rect()
    textft_rect.centerx = screen.get_rect().centerx
    textft_rect.y = 100
    screen.blit(textft, textft_rect)
    pygame.display.update()


def main():
    # 初始化棋盘数组
    board_data = [[0] * 15 for i in range(15)]
    # 初始化pygame
    pygame.init()
    pygame.display.set_caption("五子棋")
    screen = pygame.display.set_mode((16 * CELL_SIZE, 16 * CELL_SIZE))

    screen.fill(BOARD_BACKGROUND_COLOR)
    # 绘制棋盘图形
    draw_board(screen)

    is_black = True
    while True:
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                return True
            if event.type == pygame.MOUSEBUTTONDOWN and event.button == 1:
                # 获取鼠标点击时的坐标
                x, y = event.pos
                # 规则的将棋子画到落子的交点上
                chess_x = round(x / 30) * 30
                chess_y = round(y / 30) * 30
                if is_black:
                    chess_color = BLACK
                else:
                    chess_color = WHITE

                # 将当前落子转换成数组坐标存入数组
                row = chess_y // 30 - 1
                col = chess_x // 30 - 1
                if board_data[row][col] == 0:
                    # 1表示黑棋，2表示白棋
                    board_data[row][col] = 1 if is_black else 2
                    # 绘制棋子
                    pygame.draw.circle(
                        screen, chess_color, (chess_x, chess_y), 10
                    )
                    pygame.display.update()

                    # 判断是否分出生胜负
                    if judge(board_data, row, col, is_black):
                        winner = "黑方" if is_black else "白方"
                        show_winner(screen, winner)
                        time.sleep(5)
                        return True

                    # 黑白子互换
                    is_black = not is_black


if __name__ == "__main__":
    main()
